home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianDialogs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
19KB
|
691 lines
/* ScianDialogs.c
creates and manages simple dialog windows for scian
Jim Lyons
10/12/90
4/10/91 added error alerts
4/27/91 added Ask alert
5/4/91 added Choose alert
5/29/91 EMP removed library headers
7/10/91 made Choose buttons dynamically sized
7/17/91 changed Ask callback method
7/19/91 changed names of Ask and Choose to AskUser and AlertUser
9/6/91 made AskUser and AlertUser return window pointer
10/14/91 added help strings to buttons
10/25/91 made deferred task routine to close dialog windows
6/1/92 EMP fixed DismissError not to use DoClose
6/13/92 EMP changed to use method declarations, not prototypes
*/
#include "Scian.h"
#include "ScianStyle.h"
#include "ScianFontSystem.h"
#include "ScianTypes.h"
#include "ScianIDs.h"
#include "ScianArrays.h"
#include "ScianWindows.h"
#include "ScianDraw.h"
#include "ScianTextBoxes.h"
#include "ScianObjWindows.h"
#include "ScianColors.h"
#include "ScianControls.h"
#include "ScianButtons.h"
#include "ScianLists.h"
#include "ScianEvents.h"
#include "ScianTimers.h"
#include "ScianErrors.h"
#include "ScianDialogs.h"
#include "ScianTitleBoxes.h"
#include "ScianScripts.h"
/* EMP static method declarations */
static ObjPtr DrawAlertPanel();
static ObjPtr PressAlertPanel();
static ObjPtr DismissError();
static ObjPtr DoRevert();
static ObjPtr DoCancel();
static ObjPtr DoOK();
static ObjPtr DoEnter();
static ObjPtr CheckForEnter();
static ObjPtr AlertResponse();
static ObjPtr PrevError();
static ObjPtr NextError();
/* static function prototypes */
#ifdef PROTO
static void PopDialog(void);
static void DrawBorder(int , int );
#else
static void PopDialog();
static void DrawBorder();
#endif
extern WinInfoPtr allWindows;
ObjPtr dialogClass, errAlertStuff;
/*** parts stuff ***/
ObjPtr partsClass;
/* globals used by PopDialog and Ask and Choose callbacks */
static FuncTyp CallbackFunction = NULL;
static WinInfoPtr theDlg1 = NULL, theDlg2 = NULL;
static int btnNumber;
static ObjPtr theReply = NULL;
void InitDialogs()
{
dialogClass = NewObject(objWindowClass, 0);
AddToReferenceList(dialogClass);
SetVar(dialogClass, NAME, NewString("Dialog"));
/* create dummy object to store parameters for the error alert.
ERRORLIST: list of errors not yet dismissed by user
ERRORNUMBER: currently displayed error message
*/
errAlertStuff = NewObject(NULLOBJ, 0);
AddToReferenceList(errAlertStuff);
SetVar(errAlertStuff, NAME, NewString("Alert stuff"));
SetVar(errAlertStuff, ERRORLIST, NewList());
SetVar(errAlertStuff, ERRORNUMBER, NewInt(0));
partsClass = NewObject(NULLOBJ, 0);
AddToReferenceList(partsClass);
SetVar(partsClass, NAME, NewString("Parts"));
}
void KillDialogs()
/*Kills the dialog windows */
{
DeleteThing(dialogClass);
DeleteThing(errAlertStuff);
DeleteThing(partsClass);
}
/*************************************************************************** PARTS */
#ifdef PROTO
ObjPtr NewAlertPanel(int left, int right, int bottom, int top, char *name)
#else
ObjPtr NewAlertPanel(left, right, bottom, top, name)
int left, right, bottom, top;
char *name;
#endif
{
ObjPtr retVal;
retVal = NewObject(partsClass, 0);
if (retVal)
{
SetVar(retVal, NAME, NewString(name));
Set2DIntBounds(retVal, left, right, bottom, top);
SetMethod(retVal, DRAW, DrawAlertPanel);
SetMethod(retVal, PRESS, PressAlertPanel);
return retVal;
}
else return NULLOBJ;
}
static ObjPtr DrawAlertPanel(thePanel)
ObjPtr thePanel;
{
#ifdef GRAPHICS
ObjPtr theColor;
int left, right, bottom, top;
int color;
Get2DIntBounds(thePanel, &left, &right, &bottom, &top);
if (theColor = GetVar(thePanel, COLOR)) color = GetInt(theColor);
else color = UIINFOALERT;
/* draw the outside edge */
DrawRaisedEdge(left+1, right-1, bottom+1, top-1);
/* draw the color border */
FrameUIWideRect(left+EDGE+1, right-EDGE-1, bottom+EDGE+1, top-EDGE-1, ALERTBORDER, color);
/* draw the inside edge */
DrawSunkenEdge(left+ALERTBORDER+EDGE, right-ALERTBORDER-EDGE,
bottom+ALERTBORDER+EDGE, top-ALERTBORDER-EDGE);
/* draw the surface */
FillUIRect(left+ALERTBORDER+2*EDGE, right-ALERTBORDER-2*EDGE,
bottom+ALERTBORDER+2*EDGE, top-ALERTBORDER-2*EDGE, UIALERTBG);
/* draw the panel outline */
FrameUIRect(left, right, bottom, top, UIBLACK);
#endif
return NULLOBJ;
}
static ObjPtr PressAlertPanel(thePanel, mouseX, mouseY, flags)
ObjPtr thePanel;
int mouseX, mouseY;
long flags;
{
#ifdef INTERACTIVE
int left, right, bottom, top;
Get2DIntBounds(thePanel, &left, &right, &bottom, &top);
/* return if mouse outside panel */
if (mouseX < left || mouseX > right || mouseY < bottom
|| mouseY > top) return ObjFalse;
/* pop dialog window */
if (theDlg1 = (WinInfoPtr) GetVar(GetVar(thePanel, PARENT), PARENT))
{
DoTask(PopDialog);
}
/* do help if active */
if (TOOL(flags) == T_HELP)
{
ContextHelp(thePanel);
return ObjTrue;
}
#endif
/* "pass" press to contents */
return ObjFalse;
}
static void PopDialog(void) /* deferred task to pop dialog window */
{
if (theDlg1)
{
PopWindow(theDlg1);
}
theDlg1 = NULL;
}
ObjPtr MakeDialogName(dialog)
ObjPtr dialog;
/*Makes a dialog's name*/
{
ObjPtr repObj;
ObjPtr var;
repObj = GetVar(dialog, OWNERWINDOW);
if (repObj)
{
var = GetVar(repObj, NAME);
SetVar(dialog, NAME, var);
if (var)
{
SetWindowTitle(dialog, GetString(var));
}
}
return ObjTrue;
}
/**************************************************************************** GET DIALOG */
#ifdef PROTO
WinInfoPtr GetDialog(WinInfoPtr owner, ObjPtr object, char *title,
int minWidth, int minHeight, int maxWidth, int maxHeight, long flags)
#else
WinInfoPtr GetDialog(owner, object, title, minWidth, minHeight, maxWidth, maxHeight, flags)
WinInfoPtr owner;
ObjPtr object;
char *title;
int minWidth, minHeight, maxWidth, maxHeight;
long flags;
#endif
/* Returns ptr to dialog with owner owner associated with object object if it
already exists, else calls NewOpened to make one.
*/
{
WinInfoPtr retVal;
/* first see if this dialog already exists */
if ( retVal = DialogExists(owner, object) )
{
PopWindow(retVal);
}
else
{
retVal = NewObjWindow(dialogClass, title, flags, minWidth,
minHeight, maxWidth, maxHeight);
SetVar((ObjPtr) retVal, CONTENTS, NewList());
SetVar((ObjPtr) retVal, OWNERWINDOW, (ObjPtr) owner);
SetVar((ObjPtr) retVal, WHICHDIALOG, object);
SetVar((ObjPtr) retVal, CLASSID, NewInt(CLASS_DIALOG));
if (owner)
{
/*Stuff to make name change automatically*/
SetVar((ObjPtr) retVal, NAME, NewString(title));
DeclareDependency((ObjPtr) retVal, NAME, OWNERWINDOW);
DeclareIndirectDependency((ObjPtr) retVal, NAME, OWNERWINDOW, NAME);
SetMethod((ObjPtr) retVal, NAME, MakeDialogName);
}
}
return retVal;
}
WinInfoPtr DialogExists(owner, object)
WinInfoPtr owner;
ObjPtr object;
/* determine if a dialog already exists with owner owner
and associated object object. If so return its pointer, else NULL.
*/
{
WinInfoPtr w;
w = allWindows;
while (w)
{
if (IsDialog((ObjPtr) w))
{
if(GetVar((ObjPtr) w, OWNERWINDOW) == (ObjPtr) owner
&& Eql(GetVar((ObjPtr) w, WHICHDIALOG), object))
return w;
}
w = w->next;
}
return (WinInfoPtr) 0;
}
/************************************************************************* REPORT ERROR */
#ifdef PROTO
ObjPtr ReportError(char *name, char *text)
#else
ObjPtr ReportError(name, text)
char *name, *text;
#endif
{
char errMsg[256];
if (logging)
{
sprintf(errMsg, "# Error in %s: %s\n",name, text);
Log(errMsg);
}
fprintf(stderr,"Error in %s: %s\n",name, text);
return NULLOBJ;
}
/********************************************************************************* ASK */
#ifdef PROTO
WinInfoPtr AskUser(WinInfoPtr ownerWin, char *prompt, FuncTyp Callback, char *reply)
#else
WinInfoPtr AskUser(ownerWin, prompt, Callback, reply)
WinInfoPtr ownerWin;
char *prompt, *reply;
FuncTyp Callback;
#endif
{
WinInfoPtr askDlg;
ObjPtr panel, alertPanel, contents, promptBox, replyBox, revertBtn, cancelBtn, okBtn;
ObjPtr thePrompt, obj;
if (runningRemote) /* print prompt to stdout and get response now */
{
#define MAXLINELENGTH 80
char chrbuf[MAXLINELENGTH], *nl;
printf("\n***\n%s\n",prompt); /*** fix for multiline prompts? ***/
if (*reply) printf("(Default = %s)\n? ", reply);
else printf("? ");
fgets(chrbuf, MAXLINELENGTH, stdin);
if ( nl = strchr(chrbuf, '\n') ) *nl = '\0'; /* eliminate newline */
if (*chrbuf) Callback(ownerWin, chrbuf);
else Callback(ownerWin, reply); /* default */
return (WinInfoPtr) NULL;
}
/* see if dialog exists */
thePrompt = NewString(prompt);
askDlg = GetDialog(ownerWin, thePrompt, "Ask",
ASKWIDTH, ASKHEIGHT, ASKWIDTH, ASKHEIGHT,
WINUI + WINFIXEDSIZE + WINNOFRAME + WINCENTERED);
if(!askDlg) return (WinInfoPtr) NULL;
if (GetVar((ObjPtr) askDlg, REPOBJ)) /* dialog exists */
{
/* pop ask dialog */
PopWindow(askDlg);
}
else /* make the dialog box */
{
SetVar((ObjPtr) askDlg, REPOBJ, thePrompt);
contents = GetVar((ObjPtr) askDlg, CONTENTS); /* contents of window */
/* put in panel */
panel = NewPanel(greyPanelClass, 0, ASKWIDTH, 0, ASKHEIGHT);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) askDlg);
contents = GetVar(panel, CONTENTS); /* contents of panel */
/* put in pretty panel */
alertPanel = NewAlertPanel(0, ASKWIDTH, 0, ASKHEIGHT, "Ask Panel");
PrefixList(contents, alertPanel);
SetVar(alertPanel, PARENT, panel);
/* put in prompt */
promptBox = NewTextBox(SIDEMARGIN, ASKWIDTH - SIDEMARGIN,
ASKHEIGHT - TOPMARGIN - PROMPTHT, ASKHEIGHT - TOPMARGIN,
PLAIN, "Prompt Box", prompt);
PrefixList(contents, promptBox);
SetVar(promptBox, PARENT, panel);
SetVar(promptBox, UIFONT, NewInt(PROMPTTEXTFONT));
SetTextColor(promptBox, PROMPTTEXTCOLOR);
/* put in reply field */
replyBox = NewTextBox(SIDEMARGIN, ASKWIDTH - SIDEMARGIN,
BOTMARGIN + OKBTNHT + INTERSPACE,
BOTMARGIN + OKBTNHT + INTERSPACE + EDTEXTHT,
EDITABLE + WITH_PIT + ONE_LINE, "Reply", reply);
PrefixList(contents, replyBox);
SetVar(replyBox, PARENT, panel);
SetVar(replyBox, DATA, NewString(reply)); /* ref to by DoRevert */
SetMethod(replyBox, CALLBACK, Callback); /* ref by DoEnter (via DoOK) */
SetMethod(replyBox, ENTERMETHOD, DoEnter);
SelectAll(replyBox);
/* put in buttons */
if (*reply) /* put in Revert button only if given a default reply */
{
revertBtn = NewButton(SIDEMARGIN, SIDEMARGIN + OKBTNWID,
BOTMARGIN, BOTMARGIN + OKBTNHT, "Revert");
PrefixList(contents, revertBtn);
SetVar(revertBtn, PARENT, panel);
SetVar(revertBtn, REPOBJ, replyBox);
SetMethod(revertBtn, CHANGEDVALUE, DoRevert);
SetVar(revertBtn, HELPSTRING, NewString("Pressing this button \
will undo all editing and restore the text to its original state without closing the \
dialog window."));
}
cancelBtn = NewButton(ASKWIDTH - SIDEMARGIN - 2*OKBTNWID - SMALLGAP,
ASKWIDTH - SIDEMARGIN - OKBTNWID - SMALLGAP,
BOTMARGIN, BOTMARGIN + OKBTNHT, "Cancel");
PrefixList(contents, cancelBtn);
SetVar(cancelBtn, PARENT, panel);
SetMethod(cancelBtn, CHANGEDVALUE, DoCancel);
SetVar(cancelBtn, HELPSTRING, NewString("Pressing this button \
will cancel this dialog window without causing any other action."));
okBtn = NewButton(ASKWIDTH - SIDEMARGIN - OKBTNWID,
ASKWIDTH - SIDEMARGIN,
BOTMARGIN, BOTMARGIN + OKBTNHT, "OK");
PrefixList(contents, okBtn);
SetVar(okBtn, PARENT, panel);
SetMethod(okBtn, CHANGEDVALUE, DoOK);
SetVar(replyBox, BUTTON, okBtn); /* ref by DoEnter routine */
SetVar(okBtn, HELPSTRING, NewString("Pressing this button \
will dismiss this dialog window and cause the indicated action to proceed."));
/* put border around ok button to indicate default action */
obj = NewTitleBox(ASKWIDTH - SIDEMARGIN - OKBTNWID - EDGE,
ASKWIDTH - SIDEMARGIN + EDGE - 1,
BOTMARGIN - EDGE, BOTMARGIN + OKBTNHT + EDGE - 1, NIL);
PrefixList(contents, obj);
SetVar(obj, PARENT, panel);
SetVar(okBtn, REPOBJ, replyBox);
}
return askDlg;
}
static ObjPtr DoRevert(btn)
ObjPtr btn;
{
ObjPtr textBox;
textBox = GetVar(btn, REPOBJ);
SetTextBox(textBox, GetString(GetVar(textBox, DATA)));
SelectAll(textBox);
return NULLOBJ;
}
static ObjPtr DoCancel(btn)
ObjPtr btn;
{
theDlg2 = (WinInfoPtr) GetVar(GetVar(btn, PARENT), PARENT);
DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
return NULLOBJ;
}
static void AskCallback()
{
if (!theReply)
{
ReportError("AskCallback", "No reply!");
return;
}
if (!CallbackFunction)
{
ReportError("AskCallback","No completion routine!");
return;
}
if (!theDlg1)
{
ReportError("AskCallback", "No owner window!");
return;
}
IdleAllWindows();
SelWindow(theDlg1);
(*CallbackFunction)(theDlg1, GetString(theReply));
theReply = NULL;
CallbackFunction = NULL;
theDlg1 = NULL;
}
static ObjPtr DoOK(btn)
ObjPtr btn;
{
ObjPtr replyBox = GetVar(btn, REPOBJ);
CallbackFunction = GetMethod(replyBox, CALLBACK);
theReply = GetVar(replyBox, VALUE);
theDlg1 = theDlg2 = (WinInfoPtr) GetVar(GetVar(replyBox, PARENT), PARENT);
DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
DoTask(AskCallback); /* ...then do completion routine */
return NULLOBJ;
}
static ObjPtr DoEnter(replyBox)
ObjPtr replyBox;
{
ObjPtr btn;
btn = GetVar(replyBox, BUTTON); /* dialog OK button */
SetValue(btn, ObjTrue);
return NULLOBJ;
}
/************************************************************************** ALERT USER */
#ifdef PROTO
WinInfoPtr AlertUser(int level, WinInfoPtr owner, char *prompt, FuncTyp Callback,
int nBtns, ...)
#else
WinInfoPtr AlertUser(level, owner, prompt, Callback, nBtns, ...)
int level;
WinInfoPtr owner;
char *prompt;
FuncTyp Callback;
int nBtns;
#endif
{
WinInfoPtr alertWin;
ObjPtr thePrompt;
if (runningRemote) /* print prompt to stdout and get response now */
{
printf("\n***\n%s\n",prompt); /*** fix for multiline prompts? ***/
if (nBtns > 1)
{
int i;
char **p, c[4];
while (1)
{
printf("\n Enter number:\n");
p = (char **)((&nBtns) + 1); /* point to first label */
for (i=1; i<=nBtns; ++i) printf(" %d. %s\n", i, *(p+nBtns-i));
printf("? ");
fgets(c, 4, stdin);
*c -= '0';
if (*c < 1 || *c > nBtns) continue;
if (Callback) Callback(owner, nBtns - *c);
break;
}
}
return (WinInfoPtr) NULL;
}
/* see if dialog exists */
thePrompt = NewString(prompt);
alertWin = GetDialog(owner, thePrompt, "Alert",
ALERTWIDTH, ALERTHEIGHT, ALERTWIDTH, ALERTHEIGHT,
WINUI + WINFIXEDSIZE + WINNOFRAME + WINCENTERED);
if(!alertWin) return (WinInfoPtr) NULL;
if (GetVar((ObjPtr) alertWin, REPOBJ)) /* dialog exists */
{
/* pop alert */
PopWindow(alertWin);
}
else /* make the dialog box */
{
ObjPtr panel, alertPanel, contents, promptBox, btn, obj;
char **p;
int i, btnWid, nextPos, defBtnLeft;
SetVar((ObjPtr) alertWin, REPOBJ, thePrompt);
SetMethod((ObjPtr) alertWin, KEYDOWN, CheckForEnter);
SetMethod((ObjPtr) alertWin, DATA, Callback); /* save completion routine */
contents = GetVar((ObjPtr) alertWin, CONTENTS); /* contents of window */
/* put in panel */
panel = NewPanel(greyPanelClass, 0, ALERTWIDTH, 0, ALERTHEIGHT);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) alertWin);
contents = GetVar(panel, CONTENTS); /* contents of panel */
/* put in pretty panel */
alertPanel = NewAlertPanel(0, ALERTWIDTH, 0, ALERTHEIGHT, "Alert Panel");
PrefixList(contents, alertPanel);
SetVar(alertPanel, PARENT, panel);
SetVar(alertPanel, COLOR, NewInt(level));
/* put in prompt */
promptBox = NewTextBox(SIDEMARGIN, ALERTWIDTH - SIDEMARGIN,
BOTMARGIN + OKBTNHT + INTERSPACE, ALERTHEIGHT - TOPMARGIN,
PLAIN, "Prompt Box", prompt);
PrefixList(contents, promptBox);
SetVar(promptBox, PARENT, panel);
SetVar(promptBox, UIFONT, NewInt(PROMPTTEXTFONT));
/* put in the buttons */
p = (char **)((&nBtns) + 1); /* point to first button label parameter */
SetUIFont(BUTTONFONT);
if (nBtns <= 0) /* default to OK button only */
{
btn = NewButton((defBtnLeft = ALERTWIDTH - SIDEMARGIN - OKBTNWID), ALERTWIDTH - SIDEMARGIN,
BOTMARGIN, BOTMARGIN + OKBTNHT, "OK");
PrefixList(contents, btn);
SetVar(btn, PARENT, panel);
/* if callback is NULL just cancel the dialog, else call the routine */
if (Callback)
{
SetVar(btn, DATA, NewInt(0));
SetMethod(btn, CHANGEDVALUE, AlertResponse);
}
else SetMethod(btn, CHANGEDVALUE, DoCancel);
SetVar(btn, REPOBJ, (ObjPtr) alertWin);
}
else
{
nextPos = ALERTWIDTH - SIDEMARGIN + SMALLGAP; /* set up for loop */
for (i=0; i<nBtns; ++i, ++p) /* from right to left; rightmost button is zero */
{
btnWid = 2*BTNMARGIN + StrWidth(*p);
btnWid = GRIDSIZE * (int) (btnWid/GRIDSIZE + 1); /* constrain to grid */
nextPos = nextPos - SMALLGAP - btnWid;
if (i == 0) defBtnLeft = nextPos; /* remeber default btn position */
if (nextPos < SIDEMARGIN) break; /* not enough room */
btn = NewButton(nextPos, nextPos + btnWid,
BOTMARGIN, BOTMARGIN + OKBTNHT, *p);
PrefixList(contents, btn);
SetVar(btn, PARENT, panel);
SetVar(btn, DATA, NewInt(i));
SetMethod(btn, CHANGEDVALUE, AlertResponse);
SetVar(btn, REPOBJ, (ObjPtr) alertWin);
}
}
/* put border around rightmost button to indicate default action */
obj = NewTitleBox(defBtnLeft - EDGE,
ALERTWIDTH - SIDEMARGIN + EDGE - 1,
BOTMARGIN - EDGE, BOTMARGIN + OKBTNHT + EDGE - 1, NIL);
PrefixList(contents, obj);
SetVar(obj, PARENT, panel);
}
return alertWin;
}
static void AlertCallback()
{
if (!CallbackFunction)
{
return;
}
IdleAllWindows();
/*** SelWindow(theDlg1); this doesn't work ***/
(*CallbackFunction)(theDlg1, btnNumber);
CallbackFunction = NULL;
theDlg1 = NULL;
}
static ObjPtr AlertResponse(btn)
ObjPtr btn;
{
WinInfoPtr repObj;
btnNumber = GetInt(GetVar(btn, DATA)); /* button number, 0 is rightmost */
repObj = (WinInfoPtr) GetVar(btn, REPOBJ); /* the alert dialog */
theDlg2 = repObj; /* save for close task */
theDlg1 = (WinInfoPtr) GetVar((ObjPtr) repObj, OWNERWINDOW); /* save for cpl rtn */
CallbackFunction = GetMethod((ObjPtr) repObj, DATA); /* save completion routine */
DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
DoTask(AlertCallback); /* ...then do completion routine */
return ObjTrue;
}
static ObjPtr CheckForEnter(dlg, key, flags)
ObjPtr dlg; /* really a WinInfoPtr but who cares */
int key;
long flags;
{
if (key == '\r')
{
btnNumber = 0; /* default button */
theDlg2 = (WinInfoPtr) dlg; /* save for close task */
theDlg1 = (WinInfoPtr) GetVar(dlg, OWNERWINDOW); /* save for cpl rtn */
CallbackFunction = GetMethod(dlg, DATA); /* save completion routine */
DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
DoTask(AlertCallback); /* ...then do completion routine */
return ObjTrue;
}
else
{
return ObjFalse;
}
}